import json
from django.http import JsonResponse
from django.views.generic import View
from ..serializers.instListSerializer import InstListQuerySerializer, InstListSerializer
from ..utils.literUtils import handle_serializer_error, emptyValue
from django.db.models import Q
from ..models.Institution import Institution
from ..models.GlobalTables import InstitutionType, DepartmentType
from django.core.paginator import Paginator
from utils.encryptionAndDecryptionUtil import get_useraccount_from_request
from ..serializers.instInfoSerializer import InstCreateSerializer, InstInfoSerializer
from ..serializers.departInfoSerializer import DepartCreateSerializer
from ..models.Department import Department
from datetime import datetime
import traceback
from control.models.User import User


class InstView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET    
            query_list_serializer = InstListQuerySerializer(data=data)
            data_valid = query_list_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res["message"] = "参数错误：" + \
                    handle_serializer_error(
                        errors=query_list_serializer.errors)
                return JsonResponse(res)
            data = query_list_serializer.validated_data
            insts = Institution.objects.all().order_by('-create_date')
            query = Q()
            if "name" in data and data["name"] != "":
                query &= Q(name__icontains=data["name"])
            if "zh_name" in data and data["zh_name"] != "":
                query &= Q(zh_name__icontains=data["zh_name"])
            if 'ins_code' in data and data['ins_code'] != "":
                query &= Q(ins_code__icontains=data["ins_code"])
            if 'country' in data and data['country'] != "":
                query &= Q(country__icontains=data["country"])
            if 'city' in data and data['city'] != "":
                query &= Q(city__icontains=data["city"])
            if 'address' in data and data['address'] != "":
                query &= Q(address__icontains=data["address"])
            if 'postal_code' in data and data['postal_code'] != "":
                query &= Q(postal_code__icontains=data["postal_code"])
            if 'contact_number' in data and data['contact_number'] != "":
                query &= Q(contact_number__icontains=data["contact_number"])
            if 'email' in data and data['email'] != "":
                query &= Q(email__icontains=data["email"])
            if 'website' in data and data['website'] != "":
                query &= Q(website__icontains=data["website"])
            if 'founded_date' in data and data['founded_date'] != "":
                query &= Q(founded_date__icontains=data["founded_date"])
            if 'description' in data and data['description'] != "":
                query &= Q(description__icontains=data["description"])
            if 'inst_type' in data and len(data['inst_type']) != 0:
                lang_list = [x['[0]'] for x in data['inst_type']]
                query &= Q(inst_type_id__in=lang_list)

            order_list_combined = []
            prop_list = data.get('sort_prop', '').split(
                ',') if data.get('sort_prop') else []
            order_list = data.get('sort_order', '').split(
                ',') if data.get('sort_order') else []
            if len(prop_list) != len(order_list):
                res["code"] = 400
                res["message"] = "排序参数错误"
                return JsonResponse(res)
            for i in range(len(prop_list)):
                for prop, order in zip(prop_list, order_list):
                    if order.lower() == 'ascending':
                        order_list_combined.append(prop)
                    elif order.lower() == 'descending':
                        order_list_combined.append(f'-{prop}')
            if len(query) != 0:
                insts = insts.filter(query)
                
            tmp_insts = set()
            if 'departments' in data and data['departments'] != "":
                dl = data['departments'].split(";")
                for dn in dl:
                    dd = dn.strip()
                    td = Department.objects.filter(Q(name__icontains=dd) | Q(zh_name__icontains=dd))
                    for dep in td.all():
                        tmp_insts.add(dep.institution.uuid)
                # print(tmp_insts)
                insts = insts.filter(uuid__in=tmp_insts)


            if len(order_list_combined) != 0:
                insts = insts.order_by(*order_list_combined)
            total_count = insts.count()
            res_data = {}
            if "page_size" in data:
                page_size = data["page_size"]
                current_page = data["current_page"]
                paginator = Paginator(insts, page_size)
                if current_page > paginator.num_pages:
                    current_page = paginator.num_pages
                page_obj = paginator.get_page(current_page)
                res_data["current_page"] = current_page
                res_data["page_size"] = page_size
                res_data["total_count"] = total_count
                inst_list_serializer = InstListSerializer(
                    page_obj, many=True)
                res_data["objects"] = inst_list_serializer.data
                res["code"] = 200
                res["message"] = "查询成功"
                res["data"] = res_data
                return JsonResponse(res)
            res_data["total_count"] = total_count
            inst_list_serializer = InstListSerializer(
                insts, many=True)
            res_data["objects"] = inst_list_serializer.data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = res_data
            return JsonResponse(res)
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def post(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            data['founded_date'] = None if emptyValue(data['founded_date']) else datetime.fromisoformat(data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
            data['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(data['inst_type']) else data['inst_type']
                   
            departments_data = data.pop('departments', [])
            
            add_serializer = InstCreateSerializer(data=data)
            data_valid = add_serializer.is_valid()
            if not data_valid:
                print(add_serializer.errors)
                serial_errors = handle_serializer_error(
                    errors=add_serializer.errors)
                res["code"] = 400
                res["message"] = "参数错误：\n" + serial_errors
                return JsonResponse(res)
            data = add_serializer.validated_data
            data["creator"] = u
            data["last_editor"] = u
            
            i = add_serializer.save()
                    
            for depart in departments_data:
                depart['founded_date'] = None if emptyValue(depart['founded_date']) else datetime.fromisoformat(depart['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                depart['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(depart['dep_type']) else depart['dep_type']
                depart["institution"] = i.uuid
                depart_add_serializer = DepartCreateSerializer(data=depart)
                depart_data_valid = depart_add_serializer.is_valid()
                if not depart_data_valid:
                    print(depart_add_serializer.errors)
                    depart_serial_errors = handle_serializer_error(
                        errors=depart_add_serializer.errors)
                    res["code"] = 400
                    res["message"] = "参数错误：\n" + depart_serial_errors
                    return JsonResponse(res)
                depart_data = depart_add_serializer.validated_data
                depart_data["creator"] = u
                depart_data["last_editor"] = u
                depart_add_serializer.save()
                
            res["code"] = 200
            res["message"] = "新建成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    

class InstInfoView(View):
    def get(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            inst = Institution.objects.get(uuid=id)
            inst = InstInfoSerializer(inst).data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = inst
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def delete(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            i = Institution.objects.get(uuid=id)
            if i is None:
                res["code"] = 400
                res["message"] = "该条目不存在"
                return JsonResponse(res)
            
            if len(i.department_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该机构仍包含若干部门"
                return JsonResponse(res)
            
            if len(i.author_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该机构仍被若干作者引用"
                return JsonResponse(res)
            
            if len(i.publication_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该机构仍被若干出版物引用"
                return JsonResponse(res)

            i.delete()
            res["code"] = 200
            res["message"] = "删除成功"
            res["data"] = None
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def put(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            data['founded_date'] = None if emptyValue(data['founded_date']) else datetime.fromisoformat(data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
            data['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(data['inst_type']) else data['inst_type']
                   
            departments_data = data.pop('departments', [])
            
            inst = Institution.objects.get(uuid=id)   
            modify_serializer = InstCreateSerializer(instance=inst, data=data)
            data_valid = modify_serializer.is_valid()
            if not data_valid:
                print(modify_serializer.errors)
                serial_errors = handle_serializer_error(
                    errors=modify_serializer.errors)
                res["code"] = 400
                res["message"] = "参数错误：\n" + serial_errors
                return JsonResponse(res)
            data = modify_serializer.validated_data
            data["last_editor"] = u
            
            i = modify_serializer.save()
            
            for d in i.department_set.all():
                d.delete()
                    
            for depart in departments_data:
                depart['founded_date'] = None if emptyValue(depart['founded_date']) else datetime.fromisoformat(depart['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                depart['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(depart['dep_type']) else depart['dep_type']
                depart["institution"] = i.uuid
                depart_add_serializer = DepartCreateSerializer(data=depart)
                depart_data_valid = depart_add_serializer.is_valid()
                if not depart_data_valid:
                    print(depart_add_serializer.errors)
                    depart_serial_errors = handle_serializer_error(
                        errors=depart_add_serializer.errors)
                    res["code"] = 400
                    res["message"] = "参数错误：\n" + depart_serial_errors
                    return JsonResponse(res)
                depart_data = depart_add_serializer.validated_data
                depart_data["creator"] = u
                depart_data["last_editor"] = u
                depart_add_serializer.save()
                
            res["code"] = 200
            res["message"] = "编辑成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)